package me.sdau.spider.openapi.comm.aop;

import com.google.common.base.Joiner;
import lombok.extern.slf4j.Slf4j;
import me.sdau.spider.openapi.comm.utils.SystemUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.NamedThreadLocal;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;

/**
 * @author zj
 * @date 2018/3/28 16:13
 */

@Slf4j
@Aspect
@Component
public class LoggerAdvice {
    private static final ThreadLocal<Long> startTimeThreadLocal =
            new NamedThreadLocal<>("ThreadLocal StartTime");

    @Before("within(me.sdau.spider.openapi.web..*) && @annotation(loggerManage)")
    public void addBeforeLogger(JoinPoint joinPoint, LoggerManage loggerManage) {
        log.info("执行{}开始 <== path: [{}] IP: [{}]",
                loggerManage.description(),
                SystemUtil.getURI(),
                SystemUtil.getRemoteAddr());
        log.info("传入参数 <== [{}]", parseParames(joinPoint.getArgs()));
        if (log.isDebugEnabled()) {
            long beginTime = System.currentTimeMillis();//1、开始时间
            startTimeThreadLocal.set(beginTime);		//线程绑定变量（该数据只有当前请求的线程可见）
            log.debug("开始计时: {}  URI: {}", new SimpleDateFormat("HH:mm:ss.SSS")
                    .format(beginTime), SystemUtil.getURI());
        }
    }

    @AfterReturning("within(me.sdau.spider.openapi.web..*) && @annotation(loggerManage)")
    public void addAfterReturningLogger(JoinPoint joinPoint, LoggerManage loggerManage) {

        if (log.isDebugEnabled()) {
            long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量（开始时间）
            long endTime = System.currentTimeMillis(); 	//2、结束时间
            log.debug("计时结束：{}  耗时：{}  URI: {}  最大内存: {}m  已分配内存: {}m  已分配内存中的剩余空间: {}m  最大可用内存: {}m",
                    new SimpleDateFormat("HH:mm:ss.SSS").format(endTime), SystemUtil.formatDateTime(endTime - beginTime),
                    SystemUtil.getURI(), Runtime.getRuntime().maxMemory()/1024/1024, Runtime.getRuntime().totalMemory()/1024/1024, Runtime.getRuntime().freeMemory()/1024/1024,
                    (Runtime.getRuntime().maxMemory()- Runtime.getRuntime().totalMemory()+ Runtime.getRuntime().freeMemory())/1024/1024);
            //删除线程变量中的数据，防止内存泄漏
            startTimeThreadLocal.remove();
        }
    }

    private String parseParames(Object[] parames) {
        if (parames == null || parames.length == 0) {
            return "";
        }
        return Joiner.on("], [").skipNulls().join(parames);
    }
}
